<!doctype html>
<html lang="en">
<head>
  <title>WebGL Demo</title>
  <meta charset="utf-8">
  <style>
    html, body {
      width: 100%;
      height: 100%;
      margin: 0;
    }
  </style>
</head>

<body>
<canvas id="glcanvas" width="640" height="480"></canvas>
<div id="uiContainer">
  <div id="ui">
    <div id="fRotation"></div>
  </div>
</div>
</body>

<script src="https://webglfundamentals.org/webgl/resources/webgl-utils.js"></script>
<script src="https://webglfundamentals.org/webgl/resources/webgl-lessons-ui.js"></script>
<script src="https://webglfundamentals.org/webgl/resources/m4.js"></script>

<script  id="vertex-shader-3d" type="x-shader/x-vertex">
   attribute vec4 a_position;
  attribute vec4 a_color;

  varying vec4 v_color;
  uniform mat4 u_matrix;
  //uniform float u_fudgeFactor;


  void main() {
     vec4 position  = u_matrix*a_position;

     float zToDivideBy = 1.0 + position.z * 0.5;

     gl_Position = vec4(position.xyz,zToDivideBy);
     v_color=a_color;

  }
</script>
<!-- fragment shader -->
<script  id="fragment-shader-3d" type="x-shader/x-fragment">
precision mediump float;

  varying vec4 v_color;
  void main() {
    gl_FragColor = v_color;
  }
</script>

<script>
  main();

  function main() {
    var canvas = document.querySelector("#glcanvas");
    var gl = canvas.getContext("webgl");
    if (!gl) {
      return;
    }

    var program = webglUtils.createProgramFromScripts(gl, ["vertex-shader-3d", "fragment-shader-3d"]);
    //找到刚刚创建的程序属性位置
    var positionAttributeLocation = gl.getAttribLocation(program, "a_position");
    var colorLocation = gl.getAttribLocation(program, "a_color");

    var resolutionUniformLocation = gl.getUniformLocation(program, "u_matrix");


    //创建缓冲区
    var positionBuffer = gl.createBuffer();

    //绑定缓冲区
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

    //通过绑定点应用缓冲区中的数据
    setGeometry(gl);

    // Create a buffer to put colors in
    var colorBuffer = gl.createBuffer();
    // Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = colorBuffer)
    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
    // Put geometry data into buffer
    setColors(gl);

    webglUtils.resizeCanvasToDisplaySize(gl.canvas);

    //转换gl_Positon返回像素，称为屏幕空间。可用把gl.viewport把画布的当前大小传递给它
    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

    //把画布清理干净
    gl.clearColor(0, 0, 0, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.enable(gl.CULL_FACE);
    gl.enable(gl.DEPTH_TEST);

    //告诉webgl要执行那个着色器程序
    gl.useProgram(program);

    //告诉webgl如何从上面设置的缓冲区中获取数据，并将其提供给着色器中的属性
    gl.enableVertexAttribArray(positionAttributeLocation);

    //绑定位置缓冲区。
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

    // 告诉属性如何从位置缓冲区获取数据(数组_缓冲器)
    var size = 3;          // 每次迭代2个组件
    var type = gl.FLOAT;   // 数据为32位浮点数。
    var normalize = false; // 不要标准化数据
    var stride = 0;        // 0=向前移动，大小*每次迭代的大小(类型)，以获得下一个位置
    var offset = 0;        // 从缓冲区的开头开始
    gl.vertexAttribPointer(
      positionAttributeLocation, size, type, normalize, stride, offset)

    // Turn on the color attribute
    gl.enableVertexAttribArray(colorLocation);

    // Bind the color buffer.
    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);

    // Tell the attribute how to get data out of colorBuffer (ARRAY_BUFFER)
    var size = 3;                 // 3 components per iteration
    var type = gl.UNSIGNED_BYTE;  // the data is 8bit unsigned values
    var normalize = true;         // normalize the data (convert from 0-255 to 0-1)
    var stride = 0;               // 0 = move forward size * sizeof(type) each iteration to get the next position
    var offset = 0;               // start at the beginning of the buffer
    gl.vertexAttribPointer(
      colorLocation, size, type, normalize, stride, offset);


    let matrix=projection(gl.canvas.clientWidth,gl.canvas.clientHeight,400)
    matrix = m4.xRotate(matrix, 0.6981317007977318);
    matrix = m4.yRotate(matrix, 0.4363323129985824);
    matrix = m4.zRotate(matrix, 5.672320068981571);
    matrix = m4.translate(matrix, 0, 50, 0);

    gl.uniformMatrix4fv(resolutionUniformLocation, false,matrix);

    var primitiveType = gl.TRIANGLES;
    var offset = 0;
    var count = 6*16;
    gl.drawArrays(primitiveType, offset, count);

    function projection(width, height, depth) {
      // Note: This matrix flips the Y axis so 0 is at the top.
      return [
        2 / width, 0, 0, 0,
        0, -2 / height, 0, 0,
        0, 0, 2 / depth, 0,
        -1, 1, 0, 1,
      ];
    }
  }


  function setGeometry(gl) {
    gl.bufferData(
      gl.ARRAY_BUFFER,
      new Float32Array([
        // left column front
        0,   0,  0,
        0, 150,  0,
        30,   0,  0,
        0, 150,  0,
        30, 150,  0,
        30,   0,  0,

        // top rung front
        30,   0,  0,
        30,  30,  0,
        100,   0,  0,
        30,  30,  0,
        100,  30,  0,
        100,   0,  0,

        // middle rung front
        30,  60,  0,
        30,  90,  0,
        67,  60,  0,
        30,  90,  0,
        67,  90,  0,
        67,  60,  0,

        // left column back
        0,   0,  30,
        30,   0,  30,
        0, 150,  30,
        0, 150,  30,
        30,   0,  30,
        30, 150,  30,

        // top rung back
        30,   0,  30,
        100,   0,  30,
        30,  30,  30,
        30,  30,  30,
        100,   0,  30,
        100,  30,  30,

        // middle rung back
        30,  60,  30,
        67,  60,  30,
        30,  90,  30,
        30,  90,  30,
        67,  60,  30,
        67,  90,  30,

        // top
        0,   0,   0,
        100,   0,   0,
        100,   0,  30,
        0,   0,   0,
        100,   0,  30,
        0,   0,  30,

        // top rung right
        100,   0,   0,
        100,  30,   0,
        100,  30,  30,
        100,   0,   0,
        100,  30,  30,
        100,   0,  30,

        // under top rung
        30,   30,   0,
        30,   30,  30,
        100,  30,  30,
        30,   30,   0,
        100,  30,  30,
        100,  30,   0,

        // between top rung and middle
        30,   30,   0,
        30,   60,  30,
        30,   30,  30,
        30,   30,   0,
        30,   60,   0,
        30,   60,  30,

        // top of middle rung
        30,   60,   0,
        67,   60,  30,
        30,   60,  30,
        30,   60,   0,
        67,   60,   0,
        67,   60,  30,

        // right of middle rung
        67,   60,   0,
        67,   90,  30,
        67,   60,  30,
        67,   60,   0,
        67,   90,   0,
        67,   90,  30,

        // bottom of middle rung.
        30,   90,   0,
        30,   90,  30,
        67,   90,  30,
        30,   90,   0,
        67,   90,  30,
        67,   90,   0,

        // right of bottom
        30,   90,   0,
        30,  150,  30,
        30,   90,  30,
        30,   90,   0,
        30,  150,   0,
        30,  150,  30,

        // bottom
        0,   150,   0,
        0,   150,  30,
        30,  150,  30,
        0,   150,   0,
        30,  150,  30,
        30,  150,   0,

        // left side
        0,   0,   0,
        0,   0,  30,
        0, 150,  30,
        0,   0,   0,
        0, 150,  30,
        0, 150,   0]),
      gl.STATIC_DRAW);
  }

  // Fill the buffer with colors for the 'F'.
  function setColors(gl) {
    gl.bufferData(
      gl.ARRAY_BUFFER,
      new Uint8Array([
        // left column front
        200,  70, 120,
        200,  70, 120,
        200,  70, 120,
        200,  70, 120,
        200,  70, 120,
        200,  70, 120,

        // top rung front
        200,  70, 120,
        200,  70, 120,
        200,  70, 120,
        200,  70, 120,
        200,  70, 120,
        200,  70, 120,

        // middle rung front
        200,  70, 120,
        200,  70, 120,
        200,  70, 120,
        200,  70, 120,
        200,  70, 120,
        200,  70, 120,

        // left column back
        80, 70, 200,
        80, 70, 200,
        80, 70, 200,
        80, 70, 200,
        80, 70, 200,
        80, 70, 200,

        // top rung back
        80, 70, 200,
        80, 70, 200,
        80, 70, 200,
        80, 70, 200,
        80, 70, 200,
        80, 70, 200,

        // middle rung back
        80, 70, 200,
        80, 70, 200,
        80, 70, 200,
        80, 70, 200,
        80, 70, 200,
        80, 70, 200,

        // top
        70, 200, 210,
        70, 200, 210,
        70, 200, 210,
        70, 200, 210,
        70, 200, 210,
        70, 200, 210,

        // top rung right
        200, 200, 70,
        200, 200, 70,
        200, 200, 70,
        200, 200, 70,
        200, 200, 70,
        200, 200, 70,

        // under top rung
        210, 100, 70,
        210, 100, 70,
        210, 100, 70,
        210, 100, 70,
        210, 100, 70,
        210, 100, 70,

        // between top rung and middle
        210, 160, 70,
        210, 160, 70,
        210, 160, 70,
        210, 160, 70,
        210, 160, 70,
        210, 160, 70,

        // top of middle rung
        70, 180, 210,
        70, 180, 210,
        70, 180, 210,
        70, 180, 210,
        70, 180, 210,
        70, 180, 210,

        // right of middle rung
        100, 70, 210,
        100, 70, 210,
        100, 70, 210,
        100, 70, 210,
        100, 70, 210,
        100, 70, 210,

        // bottom of middle rung.
        76, 210, 100,
        76, 210, 100,
        76, 210, 100,
        76, 210, 100,
        76, 210, 100,
        76, 210, 100,

        // right of bottom
        140, 210, 80,
        140, 210, 80,
        140, 210, 80,
        140, 210, 80,
        140, 210, 80,
        140, 210, 80,

        // bottom
        90, 130, 110,
        90, 130, 110,
        90, 130, 110,
        90, 130, 110,
        90, 130, 110,
        90, 130, 110,

        // left side
        160, 160, 220,
        160, 160, 220,
        160, 160, 220,
        160, 160, 220,
        160, 160, 220,
        160, 160, 220]),
      gl.STATIC_DRAW);
  }
</script>
</html>

